package com.lt.schoolchat.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.lt.schoolchat.common.ErrorCode;
import com.lt.schoolchat.constant.Constants;
import com.lt.schoolchat.exception.BusinessException;
import com.lt.schoolchat.model.entity.User;
import com.lt.schoolchat.model.mongo.Comment;
import com.lt.schoolchat.model.mongo.FocusUser;
import com.lt.schoolchat.model.mongo.Video;
import com.lt.schoolchat.model.vo.UserVO;
import com.lt.schoolchat.service.CommentService;
import com.lt.schoolchat.service.SmallVideosService;
import com.lt.schoolchat.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: ~Teng~
 * @date: 2023/5/18 20:32
 */
@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Resource
    private MongoTemplate mongoTemplate;
    @Resource
    private SmallVideosService smallVideosService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private UserService userService;

    @Override
    public Integer like(ObjectId id, Long userId) {
        // 1. 根据视频id获取被点赞用户id
        Video video = smallVideosService.getVideoById(id);
        Long videoUserId = video.getUserId();
        // 2. 判断该用户是否已经点赞过该视频
        Query query = Query.query(Criteria.where("userId").is(userId).and("videoId").is(id));
        boolean hasComment = mongoTemplate.exists(query, Comment.class);
        if (hasComment) {
            // 已经点赞 无法再次点赞
            throw new BusinessException(ErrorCode.NOT_LIKE_AGAIN);
        }
        // 3. 保存到 MongoDB 中
        Comment comment = new Comment();
        comment.setVideoId(id);
        comment.setUserId(userId);
        comment.setPublishUserId(videoUserId);
        comment.setCreated(System.currentTimeMillis());
        mongoTemplate.save(comment);
        // 更新点赞数
        Update update = new Update();
        update.inc("likeCount", 1);
        // 设置更新参数
        FindAndModifyOptions options = new FindAndModifyOptions();
        // 获取更新后的最新数据
        options.returnNew(true);
        Comment result = mongoTemplate.findAndModify(query, update, options, Comment.class);
        video.setLikeCount(result.getLikeCount());
        // 更新点赞数
        mongoTemplate.save(video);
        return result.getLikeCount();
    }

    @Override
    public Integer unlike(ObjectId id, Long userId) {
        // 1. 根据视频id获取被点赞用户id
        Video video = smallVideosService.getVideoById(id);
        // 2. 判断该用户是否已经点赞过该视频
        Query query = Query.query(Criteria.where("userId").is(userId).and("videoId").is(id));
        boolean hasComment = mongoTemplate.exists(query, Comment.class);
        if (!hasComment) {
            // 未点赞 无法进行取消点赞
            throw new BusinessException(ErrorCode.NOT_CANCEL_LIKE);
        }
        // 3. 从 MongoDB 中删除
        // 互动更新点赞数
        Update update = new Update();
        update.inc("likeCount", -1);
        // 设置更新参数
        FindAndModifyOptions options = new FindAndModifyOptions();
        // 获取更新后的最新数据
        options.returnNew(true);
        Comment result = mongoTemplate.findAndModify(query, update, options, Comment.class);
        video.setLikeCount(result.getLikeCount());
        // 删除互动中的点赞
        mongoTemplate.remove(query, Comment.class);
        // 视频更新点赞数
        mongoTemplate.save(video);
        return result.getLikeCount();
    }

    @Override
    public void removeCommentByVideoId(ObjectId id) {
        Query query = Query.query(Criteria.where("videoId").is(id));
        mongoTemplate.remove(query, Comment.class);
    }

    @Override
    public boolean isLike(Long userId, ObjectId videoId) {
        Query query = new Query(Criteria.where("userId").is(userId).and("videoId").is(videoId));
        return mongoTemplate.exists(query, Comment.class);
    }

    @Override
    public void useFocus(Long userId, Long loginUserId) {
        // 1. 判断用户是否关注过
        Query query = Query.query(Criteria.where("userId").is(loginUserId).and("followUserId").is(userId));
        boolean hasFocus = mongoTemplate.exists(query, FocusUser.class);
        if (hasFocus) {
            // 无法再次关注
            throw new BusinessException(ErrorCode.NOT_FOLLOW_AGAIN);
        }
        FocusUser focusUser = new FocusUser();
        focusUser.setUserId(loginUserId);
        focusUser.setFollowUserId(userId);
        focusUser.setCreated(System.currentTimeMillis());
        // 2. 保存到 MongoDB
        mongoTemplate.save(focusUser);
        // 3. 保存到 Redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + userId;
        String hashKey = Constants.FOCUS_USER_KEY + loginUserId;
        stringRedisTemplate.opsForHash().put(key, hashKey, "1");
    }

    @Override
    public void useUnFocus(Long userId, Long loginUserId) {
        // 1. 判断是否关注过该用户没
        Query query = Query.query(Criteria.where("userId").is(loginUserId).and("followUserId").is(userId));
        boolean hasFocus = mongoTemplate.exists(query, FocusUser.class);
        if (!hasFocus) {
            // 没有关注 无法取消关注
            throw new BusinessException(ErrorCode.NOT_CANCEL_FOLLOW);
        }
        // 2.从 MongoDB 中删除
        mongoTemplate.remove(query, FocusUser.class);
        // 3. 从 redis 中删除
        String key = Constants.MOVEMENTS_INTERACT_KEY + userId;
        String hashKey = Constants.FOCUS_USER_KEY + loginUserId;
        stringRedisTemplate.opsForHash().delete(key, hashKey);
    }

    @Override
    public List<UserVO> findFocusMeUser(Long loginUserId) {
        List<UserVO> userVOList = new ArrayList<>();
        Query query = new Query(Criteria.where("followUserId").is(loginUserId));
        List<FocusUser> focusUsers = mongoTemplate.find(query, FocusUser.class);
        if (CollectionUtil.isEmpty(focusUsers)) {
            // 无人关注我
            return userVOList;
        }
        List<Long> userIdList = focusUsers.stream().map(FocusUser::getUserId).collect(Collectors.toList());
        List<User> userList = userService.listByIds(userIdList);
        userVOList = userList.stream().map(user -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);
            return userVO;
        }).collect(Collectors.toList());
        return userVOList;
    }
}
